package cn.metona.mq.utils;

import cn.metona.mq.core.Message;
import cn.metona.mq.core.MessageQueue;
import cn.metona.mq.core.QueueManager;

import java.time.LocalDateTime;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Logger;

/**
 * 死信队列管理器
 * 管理失败消息的存储和处理
 */
public class DLQManager {
    private static final Logger logger = Logger.getLogger(DLQManager.class.getName());

    private final ConcurrentHashMap<String, MessageQueue> dlqMap; // 死信队列映射
    private final QueueManager queueManager;

    public DLQManager() {
        this.dlqMap = new ConcurrentHashMap<>();
        this.queueManager = QueueManager.getInstance();
    }

    /**
     * 移动消息到死信队列
     */
    public void moveToDLQ(String originalQueueName, Message message) {
        if (originalQueueName == null || originalQueueName.isEmpty() || message == null) {
            logger.warning("Invalid parameters for moveToDLQ");
            return;
        }

        try {
            String dlqName = getDLQName(originalQueueName);
            MessageQueue dlq = getOrCreateDLQ(dlqName);

            // 添加死信标记
            Message dlqMessage = new Message(
                    message.topic() + ".dlq",
                    message.body(),
                    message.priority()
            );

            // 复制原始消息的元数据
            if (message.headers() != null) {
                message.headers().forEach(dlqMessage::setHeader);
            }

            // 添加死信相关信息
            dlqMessage.setHeader("DLQ-Original-Queue", originalQueueName);
            dlqMessage.setHeader("DLQ-Move-Time", LocalDateTime.now().toString());
            dlqMessage.setHeader("DLQ-Reason", "Max retry exceeded");

            dlq.sendMessage(dlqMessage);
            logger.info("Message moved to DLQ: " + dlqName + ", original messageId: " + message.messageId());

        } catch (Exception e) {
            logger.severe("Failed to move message to DLQ: " + e.getMessage());
        }
    }

    /**
     * 获取死信队列名称
     */
    private String getDLQName(String originalQueueName) {
        if (originalQueueName == null) {
            return "DLQ";
        }
        return originalQueueName + "_DLQ";
    }

    /**
     * 获取或创建死信队列
     */
    private MessageQueue getOrCreateDLQ(String dlqName) {
        if (dlqName == null || dlqName.isEmpty()) {
            throw new IllegalArgumentException("DLQ name cannot be null or empty");
        }

        return dlqMap.computeIfAbsent(dlqName, name -> {
            MessageQueue dlq = queueManager.createQueue(name, true); // 启用持久化
            logger.info("DLQ created: " + name);
            return dlq;
        });
    }

    /**
     * 从死信队列重新处理消息
     */
    public void reprocessFromDLQ(String originalQueueName) {
        if (originalQueueName == null || originalQueueName.isEmpty()) {
            logger.warning("Invalid original queue name for reprocessing");
            return;
        }

        String dlqName = getDLQName(originalQueueName);
        MessageQueue dlq = dlqMap.get(dlqName);

        if (dlq == null) {
            logger.warning("DLQ not found: " + dlqName);
            return;
        }

        MessageQueue originalQueue = queueManager.getQueue(originalQueueName);
        if (originalQueue == null) {
            logger.warning("Original queue not found: " + originalQueueName);
            return;
        }

        // 将DLQ中的消息重新发送到原队列
        // 这里可以实现具体的重新处理逻辑
        logger.info("Reprocessing messages from DLQ: " + dlqName);
    }

    /**
     * 清理死信队列
     */
    public void cleanupDLQ(String originalQueueName) {
        if (originalQueueName == null || originalQueueName.isEmpty()) {
            return;
        }

        String dlqName = getDLQName(originalQueueName);
        MessageQueue dlq = dlqMap.remove(dlqName);

        if (dlq != null) {
            dlq.clear();
            queueManager.deleteQueue(dlqName);
            logger.info("DLQ cleaned up: " + dlqName);
        }
    }

    /**
     * 获取死信队列大小
     */
    public long getDLQSize(String originalQueueName) {
        if (originalQueueName == null || originalQueueName.isEmpty()) {
            return 0;
        }

        String dlqName = getDLQName(originalQueueName);
        MessageQueue dlq = dlqMap.get(dlqName);
        return dlq != null ? dlq.size() : 0;
    }
}